package com.wskj.common.utils.ali;

import cn.hutool.core.util.IdUtil;
import com.aliyun.cloudauth20190307.Client;
import com.aliyun.cloudauth20190307.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.tearpc.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.wskj.common.utils.common.AssertUtils;

import java.util.Arrays;
import java.util.List;


/**
 * @Author: Kun
 * 接口名：InitFaceVerify。
 *
 * 服务地址：cloudauth.aliyuncs.com。
 *
 * 请求方法：HTTPS POST和GET。
 *
 * 接口说明：每次开始认证前通过本接口获取CertifyId，用来串联认证请求中的各个接口。
 *
 * 请求参数
 *
 * 名称	类型	是否必选	描述	示例值
 * SceneId	Long	是	要接入的认证场景ID。	1000000006
 * OuterOrderNo	String	是	您自定义的业务唯一标识，用于后续定位排查问题使用。
 * 支持长度为32位的字母和数字的组合，请确保唯一。
 *
 * e0c34a77f5ac40a5aa5e6ed20c35****
 * ProductCode	String	是	要接入的认证方案。取值：
 * ID_PRO。使用ID_PRO认证方案，您的用户仅需要做活体认证。
 * ID_PLUS。使用ID_PLUS认证方案，您的用户需要拍摄身份证和活体认证。
 * 说明 如果您的业务需要同步采集身份证信息，可选择ID_PLUS方案。
 * ID_PRO
 * Model	String	否	要进行活体检测的类型。取值：
 * LIVENESS（默认）：动作活体检测。
 * PHOTINUS_LIVENESS：动作活体+炫彩活体双重检测。
 * 说明 仅Android SDK 1.2.6及以上版本、iOS SDK 1.2.4及以上版本支持设置活体检测模式。
 * LIVENESS
 * CertType	String	是	您的终端用户传入的证件类型。
 * 当前仅支持身份证，取值固定为IDENTITY_CARD。
 * 说明 当ProductCode为ID_PLUS时，CertType为非必填字段。
 * IDENTITY_CARD
 * CertName	String	是	您的终端用户的真实姓名。
 * 说明 当ProductCode为ID_PLUS时，CertName为非必填字段。
 * 张三
 * CertNo	String	是	您的终端用户的证件号码。
 * 说明 当ProductCode为ID_PLUS时，CertNo为非必填字段。
 * 330103xxxxxxxxxxxx
 * MetaInfo	String	是	MetaInfo环境参数，需要通过客户端SDK获取。	{"zimVer":"3.0.0","appVersion": "1","bioMetaInfo": "4.1.0:11501568,0","appName": "com.aliyun.antcloudauth","deviceType": "ios","osVersion": "iOS 10.3.2","apdidToken": "","deviceModel": "iPhone9,1"}
 * Mobile	String	否	您的终端用户的手机号码。	130xxxxxxxx
 * Ip	String	否	您的终端用户的IP。	114.xxx.xxx.xxx
 * UserId	String	否	您自定义的用户ID，请保持唯一。	123456789
 * CallbackUrl	String	否	认证结果的回调通知地址，必须以https开头。
 * 平台在完成认证后会回调该地址，并自动添加certifyId、passed和subcode字段，示例：https://www.aliyun.com？certifyId=xxxx&passed=T&subcode=200。
 *
 * https://www.aliyun.com
 * CallbackToken	String	否	安全Token，由您自行生成，用于防重复、防篡改校验。
 * 如果设置了该值会在回调地址显示CallbackToken字段。
 *
 * NMjvQanQgplBSaEI0sL86WnQplB
 *
 * 返回数据
 * 名称	类型	描述	示例值
 * RequestId	String	请求ID。	130A2C10-B9EE-4D84-88E3-5384FF039795
 * Message	String	请求消息的响应信息。	success
 * Code	String	返回码。关于返回码的具体信息，请参见下方返回Code和Message说明。	200
 * ResultObject.CertifyId	String	实人认证唯一标识。	91707dc296d469ad38e4c5efa6a0****
 */
public class InitFaceVerify {

    /**
     * 实人认证-获取认证ID
     * @param MetaInfo
     * @param userId
     * @return
     */
    public static String getCertifyId(String AccessKeyID,String AccessKeySecret,Long SceneId,String MetaInfo,Long userId){
        InitFaceVerifyRequest request = new InitFaceVerifyRequest();
        // 请输入场景ID+L。
        request.setSceneId(SceneId);
        // 设置商户请求的唯一标识。
        request.setOuterOrderNo(IdUtil.fastSimpleUUID());
        // 认证方案。
        // ID_PRO。使用ID_PRO认证方案，您的用户仅需要做活体认证。
        //ID_PLUS。使用ID_PLUS认证方案，您的用户需要拍摄身份证和活体认证。

        request.setProductCode("ID_PLUS");
        // 模式。
        request.setModel("LIVENESS");
        request.setCertType("IDENTITY_CARD");
        // 说明 当ProductCode为ID_PLUS时，CertName为非必填字段
        //request.setCertName("张三");
        // 当ProductCode为ID_PLUS时，CertNo为非必填字段。
        //request.setCertNo("xxxx");
        // MetaInfo环境参数。
        request.setMetaInfo(MetaInfo);
        //request.setMobile("130xxxxxxxx");
        //request.setIp("114.xxx.xxx.xxx");
        request.setUserId(String.valueOf(userId));
        //request.setCallbackUrl("https://www.aliyundoc.com");
        //request.setCallbackToken("xxxxx");

        // 推荐，支持服务路由。
        InitFaceVerifyResponse response = initFaceVerifyAutoRoute(request,AccessKeyID,AccessKeySecret);

        // 不支持服务自动路由。
        //InitFaceVerifyResponse response = initFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request);
        AssertUtils.isTrue("200".equals(response.getCode()),response.getMessage());
        System.out.println(response.getRequestId());
        System.out.println(response.getCode());
        System.out.println(response.getMessage());
        System.out.println(response.getResultObject() == null ? null
                : response.getResultObject().getCertifyId());
        return response.getResultObject() == null ? null
                : response.getResultObject().getCertifyId();
    }


    private static InitFaceVerifyResponse initFaceVerifyAutoRoute(InitFaceVerifyRequest request,String AccessKeyID,String AccessKeySecret) {
        // 第一个为主区域Endpoint，第二个为备区域Endpoint。
        List<String> endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com",
                "cloudauth.cn-beijing.aliyuncs.com");
        InitFaceVerifyResponse lastResponse = null;
        for (String endpoint : endpoints) {
            try {
                InitFaceVerifyResponse response = initFaceVerify(endpoint, request,AccessKeyID, AccessKeySecret);
                lastResponse = response;

                // 服务端错误，切换到下个区域调用。
                if (response != null && "500".equals(response.getCode())) {
                    continue;
                }

                return response;
            } catch (Exception e) {
                // 网络异常，切换到下个区域调用。
                if (e.getCause() instanceof TeaException) {
                    TeaException teaException = ((TeaException)e.getCause());
                    if (teaException.getData() != null && "ServiceUnavailable".equals(
                            teaException.getData().get("Code"))) {
                        continue;
                    }
                }

                if (e.getCause() instanceof TeaUnretryableException) {
                    continue;
                }
            }
        }

        return lastResponse;
    }

    private static InitFaceVerifyResponse initFaceVerify(String endpoint, InitFaceVerifyRequest request,String AccessKeyID,String AccessKeySecret)
            throws Exception {
        Config config = new Config();
        config.setAccessKeyId(AccessKeyID);
        config.setAccessKeySecret(AccessKeySecret);
        config.setEndpoint(endpoint);
        // 设置http代理。
        //config.setHttpProxy("http://xx.xx.xx.xx:xxxx");
        // 设置https代理。
        //config.setHttpsProxy("https://xx.xx.xx.xx:xxxx");
        Client client = new Client(config);
        // 创建RuntimeObject实例并设置运行参数。
        RuntimeOptions runtime = new RuntimeOptions();
        runtime.readTimeout = 10000;
        runtime.connectTimeout = 10000;
        return client.initFaceVerify(request, runtime);
    }
}
